﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;
using System.Threading;
using System.IO;

namespace loader
{
    public partial class extractfiles : Form
    {
        private string loc;
        private ZipFile zip;
        private byte[] buffer;
        private Thread ext;
        private bool hasdata;

        private delegate void UpdateProgressCallback(long fsize, long fpos);
        private delegate void CloseCallback();
        private delegate void ExtractFinishedCallback();

        public string Path
        {
            get { return this.loc; }
            set { this.loc = value; }
        }

        private void updateprogress(long fsize, long fpos)
        {
            this.pbExtracted.Value = Convert.ToInt32((fpos * 100) / fsize);
        }

        void Quit()
        {
            this.Visible = false;
            this.Close();
        }

        public void ExtractFinished()
        {
            this.Visible = false;
            MessageBox.Show(Program.localee["ext_finish"] + loc, Program.localee["iform_txt"], MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.Close();
        }

        public extractfiles()
        {
            InitializeComponent();

            if (Program.localee.issupported)
            {
                this.Text = Program.localee["ext_title"];
                this.lb_extract.Text = Program.localee["ext_caption"];
            }

            if (string.IsNullOrEmpty(loc))
            {
                FolderBrowserDialog fb = new FolderBrowserDialog();
                fb.RootFolder = Environment.SpecialFolder.Desktop;
                fb.Description = Program.localee["path_select"];
                if (fb.ShowDialog() == DialogResult.OK) this.loc = fb.SelectedPath;
                else
                {
                    MessageBox.Show(Program.localee["ext_cancel"], Program.localee["iform_txt"], MessageBoxButtons.OK, MessageBoxIcon.Information);
                    Program.needtoquit = true;
                    return;
                }
                try
                {
                    zip = new ZipFile(Application.ExecutablePath);
                    if (zip.Count > 0)
                    {
                        this.hasdata = true;
                        setpass pwd = new setpass();
                        if (zip[0].IsCrypted)
                        {
                            if (pwd.ShowDialog() == DialogResult.OK) zip.Password = pwd.passwd;
                            else
                            {
                                Program.needtoquit = true;
                                return;
                            }
                        }
                        buffer = new byte[16384];
                        ext = new Thread(extract);
                        ext.Start();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Program.needtoquit = true;
                }
            }
        }

        void extract()
        {
            if (hasdata)
            {
                try
                {
                    if (!Directory.Exists(this.loc)) Directory.CreateDirectory(this.loc);
                    int read;
                    for (int index = 0; index < zip.Count; ++index)
                    {
                        if (zip[index].IsFile)
                        {
                            Stream input = zip.GetInputStream(index);
                            using (FileStream output = File.OpenWrite(load.MergePaths(loc, zip[index].Name)))
                            {
                                do
                                {
                                    read = input.Read(this.buffer, 0, this.buffer.Length);
                                    output.Write(buffer, 0, read);
                                }
                                while (read > 0);
                            }
                        }
                        this.Invoke(new UpdateProgressCallback(this.updateprogress), new object[] { zip.Count, index });
                    }
                    this.Invoke(new CloseCallback(this.ExtractFinished));
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Program.localee["error_txt"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.Invoke(new CloseCallback(Quit));
                }
            }
        }
    }
}
